package com.donleo.security.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.donleo.common.api.CommonResult;
import com.donleo.common.relation.UserRoleRelation;
import com.donleo.common.utils.CommonPath;
import com.donleo.security.mapper.UserMapper;
import com.donleo.security.mapper.UserRoleRelationMapper;
import com.donleo.security.model.Permission;
import com.donleo.security.model.User;
import com.donleo.security.service.RedisService;
import com.donleo.security.service.UserService;
import com.donleo.security.utils.JwtTokenUtil;
import com.donleo.security.vo.LoginParams;
import com.donleo.security.vo.UserVo;
import org.apache.commons.lang.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.Date;
import java.util.HashSet;
import java.util.List;

/**
 * @author liangd
 * @since 2021-01-15 17:33
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private UserRoleRelationMapper userRoleRelationMapper;

    @Autowired
    private RedisService redisService;

    @Override
    public User getUserByCode(String code) {
        List<User> users = userMapper.getUserByCode(code);
        Assert.isTrue(users.size() == 1, "您输入的账户不存在，或者有多个相同的账户");
        return users.get(0);
    }

    @Override
    public List<Permission> getPermissionsByUserCode(String userCode) {
        return userMapper.getPermissionsByUserCode(userCode);
    }

    @Override
    public String login(LoginParams loginParams) {
        String code = loginParams.getCode();
        Assert.notNull(code, "账号必须不能为空");
        String password = loginParams.getPassword();
        Assert.notNull(password, "密码必须不能为空");
        User userByCode = getUserByCode(code);
        //判断用户输入的密码与数据库中查出来的密码是否相等
        boolean matches = passwordEncoder.matches(password, userByCode.getPassword());
        if (matches) {
            //查询用户权限
            List<Permission> permissionsByUserCode = getPermissionsByUserCode(userByCode.getCode());
            //去重
            HashSet<Permission> permissions = new HashSet<>(permissionsByUserCode);
            //赋值
            userByCode.setAuthorities(permissions);
            //生成token
            return jwtTokenUtil.generateToken(userByCode);
        }
        return null;
    }

    @Override
    public CommonResult checkAuth(String userCode, String uri) {
        List<Permission> permissions = getPermissionsByUserCode(userCode);
        //只要有一个路径匹配就返回true
        boolean b = permissions.stream().anyMatch(permission -> StringUtils.equals(permission.getUri(), uri));
        if (b) {
            return CommonResult.success(true);
        }
        return CommonResult.failed();
    }

    @Override
    public boolean isValidateCode(String validateCode) {
        String backValidateCode = (String) redisService.get("backValidateCode");
        return !backValidateCode.equals(validateCode);
    }

    @Override
    public Boolean register(User user) {
        String code = user.getCode();
        Assert.notNull(code, "用户编号不能为空");
        String password = user.getPassword();
        Assert.notNull(password, "密码不能为空");
        List<User> users = userMapper.getUserByCode(code);
        if (users.size() >= 1) {
            return false;
        }
        user.setPassword(passwordEncoder.encode(password));
        user.setCreateTime(new Date());
        user.setDataEnable(CommonPath.YES.getValue());
        int i = userMapper.insert(user);
        if (i > 0) {
            UserRoleRelation userRoleRelation = UserRoleRelation.builder().userCode(user.getCode()).roleCode("role:student").build();
            userRoleRelationMapper.insert(userRoleRelation);
        }
        return true;
    }

    @Override
    public User loadUserAuthorityByUserCode(String userCode) {
        boolean b = redisService.hasKey("user::pmsAuthors:" + userCode);
        User user;
        if (b) {
            user = (User) redisService.get("user::pmsAuthors:" + userCode);
        } else {
            List<User> users = userMapper.getUserByCode(userCode);
            user = users.get(0);

            List<Permission> permissionList = userMapper.getPermissionsByUserCode(user.getCode());
            //获取用户拥有的权限
            HashSet<Permission> permissions = new HashSet<>(permissionList);
            user.setAuthorities(permissions);
            redisService.set("user::pmsAuthors:" + userCode, user, 30 * 60);
        }
        return user;
    }

    @Override
    public void frozenUser(User user) {
        userMapper.updateById(user);
    }

    @Override
    public boolean isFrozenUser(String code) {
        List<User> userList = userMapper.getUserByCode(code);
        User user = userList.get(0);
        return user.getDataEnable().equals(CommonPath.NO.getValue());
    }

    @Override
    public List<User> findAll(UserVo userVo) {
        return userMapper.findAll(userVo);
    }

    @Override
    public long getCount(UserVo userVo) {
        return userMapper.getCount(userVo);
    }

    @Override
    public CommonResult updateUser(User user) {
        user.setUpdateTime(new Date());
        int i = userMapper.updateById(user);
        if (i > 0) {
            return CommonResult.success(i);
        } else {
            return CommonResult.failed();
        }
    }

    @Override
    public User findById(Integer id) {
        return userMapper.findById(id);
    }

    @Override
    public List<User> findUserByRoleCode(String roleCode) {
        return userMapper.findUserByRoleCode(roleCode);
    }

    @Override
    public List<User> findUserByTeamCode(String teamCode, Integer pageNum, Integer pageSize) {
        return userMapper.findByTeam(teamCode, pageNum, pageSize);
    }

    @Override
    public long getCountByTeamCode(String teamCode) {
        return userMapper.getCountByTeamCode(teamCode);
    }

    @Override
    public List<User> findUngroupedUser() {

        return userMapper.findUngroupedUser();
    }

    @Override
    public CommonResult getUserNameByCode(String code) {
        User byCode = userMapper.findByCode(code);
        return CommonResult.success(byCode.getUsername());
    }
}
